#pragma once
#include<functional>
#include"noncopyable.h"
#include<vector>
#include<atomic>
#include"Timestamp.h"
#include<memory>
#include"CurrentThread.h"
#include<mutex>
// Poller 在前面写的里面实现了poll 和 epoll 两种
// 事件循环类，主要包含了两个模块 Channel Poller(epoll 的抽象)
// one loop per thread 一个线程一个EventLoop
// 每一个线程都有一个EventLoop，每一个EventLoop可以关心海量Channel

class Channel;
class Poller;
// 我们写的时候用的是map<int,Channel> 看看这里怎么实现！
class EventLoop
{
    public:
    using Functor = std::function<void()>;
    
    EventLoop();
    ~EventLoop();
    
    // 开启事件循环
    void loop();
    // 退出事件循环
    void quit();

    Timestamp pollReturntime() const {return pollReturntime_;}
    // 在当前loop中执行cb
    void runInLoop(Functor cb);
    // 把cb放入队列中，唤醒loop所在的线程，执行cb
    void queueInLoop(Functor cb); 
    // 用来唤醒loop所在的线程的
    void wakeup();

    // 判断EventLoop 对象是否在自己的线程里面。
    bool isInLoopThread() const {return threadId_ == CurrentThread::tid();}

    // EventLoop的方法 =》 Poller的方法
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);


    
    private:
    void handlerRead(); // wake up
    void doPendingFunctors();
    using ChannelList = std::vector<Channel*>;

    std::atomic_bool looping_; // 原子操作，通过CAS实现
    std::atomic_bool quit_;    // 标识退出loop循环
    const pid_t threadId_;     // 记录当前loop所在线程的id 
    Timestamp pollReturntime_; // poller 返回发生事件的channels的时间点
    std::unique_ptr<Poller> poller_; // 每一个EventLoop 里面有一个Poller

    int wakeupFd_; // 重要，唤醒subReactor，通过轮询算法选择一个subloop，通过该成员唤醒subloop处理channels
    std::unique_ptr<Channel> wakeupChannel_;

    ChannelList activeChannels_;  // 维护了一批量的管道
    Channel* currentActiveChannel_; // 主要做一些断言操作

    std::atomic_bool callingPendingFunctors_;// 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pendingFunctors_;  // 存储loop需要执行的所有的回调操作
    std::mutex mutex_;                      // 互斥锁，用来保护上面vector容器的线程安全 
};